/*
 * Copyright (c) 2010 All Inclusive Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.allinclusive.fw.web.struts.taglib;

import java.text.SimpleDateFormat;

import javax.servlet.jsp.JspException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.struts.taglib.bean.WriteTag;

import com.googlecode.allinclusive.fw.commons.util.ImperialCalendarUtil;
import com.googlecode.allinclusive.fw.commons.util.ImperialCalendar.WAREKI_MODE;

/**
 * 文字列を色々と変換して出力する為のタグ。
 * 以下のような機能を持つ。
 * <lu>
 * <li>西暦文字列を任意の書式の和暦文字列に変換</li>
 * <li>日付・時間文字列を任意の書式の日付・時間文字列に変換</li>
 * </lu>
 * 
 */
public class CustomWriteTag extends WriteTag {

    /**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = -1915021116625134488L;
	
	/* 西暦文字列のフォーマット*/
	public static final String DEFAULT_SEIREKI_FORMAT = "yyyyMMdd";
	
	/* 和暦文字列のフォーマット*/
	public static final String DEFAULT_WAREKI_FORMAT = "GGGGyy年MM月dd日";

	/* 和暦文字列のモード*/
	public static final String DEFAULT_WAREKI_MODE = "ymd";
	
	/* 指定した西暦文字列のフォーマット */
    private String inFormat = DEFAULT_SEIREKI_FORMAT;
    
    /* 出力するタイプ*/
    private String formatType = "";

    /* 出力する和暦のモード (出力するフォーマットタイプはwarekiの場合のみ)*/
    private String warekiMode = DEFAULT_WAREKI_MODE;
    
    /**
     * 指定文字列のフォーマットを取得します
     * @return　指定文字列のフォーマット
     */
    public String getInFormat() {
		return inFormat;
	}

    /**
     * 指定文字列のフォーマットを設定します
     * @param inFormat　指定文字列のフォーマット
     */
	public void setInFormat(String inFormat) {
		this.inFormat = inFormat;
	}

	/**
	 * 出力するタイプを取得します
	 * @return　出力するタイプ
	 */
	public String getFormatType() {
		return formatType;
	}

	/**
	 * 出力するタイプを設定します
	 * @param outFormat　出力するタイプ
	 */
	public void setFormatType(String formatType) {
		this.formatType = formatType;
	}

	/**
	 * 出力する和暦のモードを取得します
	 * @return　出力する和暦のモード
	 */
	public String getWarekiMode() {
		return warekiMode;
	}

	/**
	 * 出力する和暦のモードを設定します
	 * @param warekiMode　出力する和暦のモード
	 */
	public void setWarekiMode(String warekiMode) {
		this.warekiMode = warekiMode;
	}
	

	/**
	 * @see WriteTag#formatValue
	 */
	@Override
	protected String formatValue(Object valueToFormat) throws JspException {
		
		// 数値フォーマット
		if (valueToFormat instanceof Number && StringUtils.equalsIgnoreCase(formatType, "number")) {
			return super.formatValue(valueToFormat);
		} else if (valueToFormat instanceof String && StringUtils.equalsIgnoreCase(formatType, "number")) {
			return super.formatValue(NumberUtils.toDouble((String) valueToFormat));
		} 
		
		//　日時フォーマット
		if (valueToFormat instanceof java.util.Date && StringUtils.equalsIgnoreCase(formatType, "date")) {
			return super.formatValue(valueToFormat);
		} else if (valueToFormat instanceof String && StringUtils.equalsIgnoreCase(formatType, "date")) {
			try {
				SimpleDateFormat sdf = new SimpleDateFormat(inFormat);
				java.util.Date date = sdf.parse((String) valueToFormat);
				return super.formatValue(date);
			} catch (Exception e) {
				formatStr = null;
				return super.formatValue(valueToFormat);
			}
		}
		
		// 和暦フォーマット
		if (valueToFormat instanceof java.util.Date && StringUtils.equalsIgnoreCase(formatType, "wareki")) {
			return ImperialCalendarUtil.getWarekiString((java.util.Date) valueToFormat, formatStr);
		} else if (valueToFormat instanceof String && StringUtils.equalsIgnoreCase(formatType, "wareki")) {
			return formatWareki((String) valueToFormat);
		}
		
		return super.formatValue(valueToFormat);
	}
    /**
	 * 和暦文字列の生成を行う。
	 * 生成する和暦文字列のフォーマットは、<code>outFormat</code>出指定されたものに従う
	 * @param value 変換対象文字列
	 * @return フォーマット後の文字列
	 */
	private String formatWareki(Object value) throws JspException {
		
		//　フォーマット未指定の場合、デフォルトフォーマットを利用する
		if (StringUtils.isEmpty(formatStr) && StringUtils.isNotEmpty(formatKey)) {
			formatStr = retrieveFormatString(this.formatKey);
		}
		if (StringUtils.isEmpty(formatStr)) {
			formatStr = DEFAULT_WAREKI_FORMAT;
		}
		
		if (value instanceof java.util.Date) {
			//　西暦Dateを指定するフォーマット和暦文字列を戻す。
			return ImperialCalendarUtil.getWarekiString((java.util.Date)value, formatStr);
		} else if (value instanceof String) {
			//　西暦文字列を指定するフォーマット和暦文字列を戻す。
			WAREKI_MODE mode = StringUtils.equalsIgnoreCase(warekiMode, "ym") ? WAREKI_MODE.YM : WAREKI_MODE.YMD;
			return ImperialCalendarUtil.getWarekiString((String)value, inFormat, formatStr, mode);
		} else {
			return super.formatValue(value);
		}
	}
}
